from datetime import datetime, timedelta
from sqlalchemy import func
from database import db
from models import Device, DeviceData, ProductionBatch

class DataService:
    """Service for processing and analyzing device data."""
    
    @staticmethod
    def get_device_statistics(device_id=None, period='day'):
        """
        Get statistics for a device or all devices over a specified period.
        
        Args:
            device_id: Optional device ID to filter by
            period: Time period ('day', 'week', 'month')
            
        Returns:
            Dictionary of statistics
        """
        if period == 'day':
            start_time = datetime.utcnow() - timedelta(days=1)
        elif period == 'week':
            start_time = datetime.utcnow() - timedelta(days=7)
        elif period == 'month':
            start_time = datetime.utcnow() - timedelta(days=30)
        else:
            start_time = datetime.utcnow() - timedelta(days=1)
        
        query = DeviceData.query.filter(DeviceData.timestamp >= start_time)
        
        if device_id:
            device = Device.query.filter_by(device_id=device_id).first()
            if device:
                query = query.filter_by(device_id=device.id)
        
        # Calculate statistics
        total_production = query.with_entities(
            func.sum(DeviceData.production_length)
        ).scalar() or 0
        
        avg_speed = query.with_entities(
            func.avg(DeviceData.production_speed)
        ).scalar() or 0
        
        max_speed = query.with_entities(
            func.max(DeviceData.production_speed)
        ).scalar() or 0
        
        data_points = query.count()
        
        return {
            'period': period,
            'total_production': float(total_production),
            'average_speed': float(avg_speed),
            'max_speed': float(max_speed),
            'data_points': data_points
        }
    
    @staticmethod
    def check_device_status():
        """
        Check the status of all devices and update if necessary.
        Devices that haven't sent data in the last 5 minutes are marked as offline.
        """
        cutoff_time = datetime.utcnow() - timedelta(minutes=5)
        
        # Find devices that haven't updated recently
        offline_devices = Device.query.filter(
            Device.last_update < cutoff_time,
            Device.status == 'online'
        ).all()
        
        # Update their status to offline
        for device in offline_devices:
            device.status = 'offline'
        
        if offline_devices:
            db.session.commit()
            
        return len(offline_devices)
    
    @staticmethod
    def get_production_efficiency(batch_id=None):
        """
        Calculate production efficiency for a batch or overall.
        
        Args:
            batch_id: Optional batch ID to filter by
            
        Returns:
            Dictionary with efficiency metrics
        """
        if batch_id:
            batch = ProductionBatch.query.get(batch_id)
            if not batch:
                return {'error': 'Batch not found'}
            
            if batch.target_length and batch.actual_length:
                efficiency = (batch.actual_length / batch.target_length) * 100
            else:
                efficiency = 0
                
            return {
                'batch_id': batch.id,
                'batch_number': batch.batch_number,
                'efficiency': efficiency,
                'target': batch.target_length,
                'actual': batch.actual_length
            }
        
        # Calculate overall efficiency
        batches = ProductionBatch.query.filter(
            ProductionBatch.status == 'completed',
            ProductionBatch.target_length.isnot(None),
            ProductionBatch.actual_length.isnot(None)
        ).all()
        
        if not batches:
            return {'overall_efficiency': 0, 'batch_count': 0}
        
        total_target = sum(batch.target_length for batch in batches)
        total_actual = sum(batch.actual_length for batch in batches)
        
        if total_target > 0:
            overall_efficiency = (total_actual / total_target) * 100
        else:
            overall_efficiency = 0
            
        return {
            'overall_efficiency': overall_efficiency,
            'batch_count': len(batches),
            'total_target': total_target,
            'total_actual': total_actual
        }
